<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>高级VR全景查看器</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Arial', sans-serif;
            overflow: hidden;
            background: #000;
            color: white;
        }
        
        #canvas-container {
            width: 100vw;
            height: 100vh;
            position: relative;
        }
        
        canvas {
            display: block;
        }
        
        .loading-overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            z-index: 100;
            transition: opacity 0.5s;
        }
        
        .spinner {
            width: 60px;
            height: 60px;
            border: 5px solid rgba(255, 255, 255, 0.3);
            border-radius: 50%;
            border-top-color: #4CAF50;
            animation: spin 1s ease-in-out infinite;
        }
        
        @keyframes spin {
            to { transform: rotate(360deg); }
        }
        
        .loading-text {
            margin-top: 20px;
            font-size: 18px;
        }
        
        .control-panel {
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0, 0, 0, 0.6);
            padding: 15px 20px;
            border-radius: 30px;
            display: flex;
            gap: 15px;
            backdrop-filter: blur(5px);
            z-index: 10;
        }
        
        .control-btn {
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background: rgba(255, 255, 255, 0.2);
            border: none;
            color: white;
            font-size: 20px;
            cursor: pointer;
            transition: all 0.3s;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .control-btn:hover {
            background: rgba(255, 255, 255, 0.3);
            transform: scale(1.1);
        }
        
        .control-btn.active {
            background: #4CAF50;
            box-shadow: 0 0 15px rgba(76, 175, 80, 0.5);
        }
        
        .info-panel {
            position: absolute;
            top: 20px;
            right: 20px;
            background: rgba(0, 0, 0, 0.6);
            padding: 15px;
            border-radius: 15px;
            max-width: 300px;
            backdrop-filter: blur(5px);
            z-index: 10;
            transform: translateX(0);
            transition: transform 0.5s;
        }
        
        .info-panel.hidden {
            transform: translateX(400px);
        }
        
        .info-panel h2 {
            margin-bottom: 10px;
            color: #4CAF50;
        }
        
        .toggle-info {
            position: absolute;
            top: 20px;
            right: 20px;
            z-index: 11;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background: rgba(255, 255, 255, 0.2);
            border: none;
            color: white;
            font-size: 20px;
            cursor: pointer;
            transition: all 0.3s;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .hotspot {
            position: absolute;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background: rgba(76, 175, 80, 0.7);
            border: 2px solid white;
            cursor: pointer;
            transform: translate(-50%, -50%);
            z-index: 5;
            animation: pulse 2s infinite;
        }
        
        @keyframes pulse {
            0% { box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.7); }
            70% { box-shadow: 0 0 0 10px rgba(76, 175, 80, 0); }
            100% { box-shadow: 0 0 0 0 rgba(76, 175, 80, 0); }
        }
        
        .hotspot-tooltip {
            position: absolute;
            background: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 8px 12px;
            border-radius: 8px;
            white-space: nowrap;
            transform: translate(-50%, -100%);
            margin-top: -15px;
            opacity: 0;
            transition: opacity 0.3s;
            pointer-events: none;
        }
        
        .hotspot:hover .hotspot-tooltip {
            opacity: 1;
        }
        
        .fullscreen-btn {
            position: absolute;
            top: 20px;
            left: 20px;
            z-index: 10;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            background: rgba(255, 255, 255, 0.2);
            border: none;
            color: white;
            font-size: 20px;
            cursor: pointer;
            transition: all 0.3s;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .scene-selector {
            position: absolute;
            bottom: 90px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0, 0, 0, 0.6);
            padding: 10px;
            border-radius: 15px;
            display: flex;
            gap: 10px;
            backdrop-filter: blur(5px);
            z-index: 10;
        }
        
        .scene-thumb {
            width: 60px;
            height: 40px;
            border-radius: 5px;
            overflow: hidden;
            cursor: pointer;
            opacity: 0.7;
            transition: opacity 0.3s;
        }
        
        .scene-thumb:hover, .scene-thumb.active {
            opacity: 1;
            transform: scale(1.05);
        }
        
        .scene-thumb img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        
        @media (max-width: 768px) {
            .control-btn {
                width: 45px;
                height: 45px;
                font-size: 18px;
            }
            
            .info-panel {
                max-width: 250px;
                font-size: 14px;
            }
            
            .toggle-info, .fullscreen-btn {
                width: 45px;
                height: 45px;
                font-size: 18px;
            }
        }
    </style>
</head>
<body>
    <div id="canvas-container">
        <div class="loading-overlay">
            <div class="spinner"></div>
            <div class="loading-text">加载全景图中...</div>
        </div>
        
        <button class="toggle-info">ℹ️</button>
        <button class="fullscreen-btn">⛶</button>
        
        <div class="info-panel">
            <h2>VR全景查看器</h2>
            <p>使用鼠标拖动来查看全景，滚轮缩放。点击热点查看详细信息。</p>
            <p>支持在全景场景之间切换，体验沉浸式VR环境。</p>
        </div>
        
        <div class="scene-selector">
            <div class="scene-thumb active" data-scene="pano1">
                <img src="file/image/20250917/pano.jpg" alt="场景1" onerror="this.src='https://via.placeholder.com/60x40/3366cc/ffffff?text=场景1'">
            </div>
            <div class="scene-thumb" data-scene="pano2">
                <img src="file/image/20250917/pano1.jpg" alt="场景2" onerror="this.src='https://via.placeholder.com/60x40/cc3366/ffffff?text=场景2'">
            </div>
            <div class="scene-thumb" data-scene="pano3">
                <img src="file/image/20250917/pano.jpg" alt="场景3" onerror="this.src='https://via.placeholder.com/60x40/33cc66/ffffff?text=场景3'">
            </div>
        </div>
        
        <div class="control-panel">
            <button class="control-btn" id="zoom-in">+</button>
            <button class="control-btn" id="zoom-out">-</button>
            <button class="control-btn" id="reset-view">↺</button>
            <button class="control-btn" id="vr-mode">VR</button>
        </div>
    </div>

    <script>
        // 初始化变量
        let scene, camera, renderer, controls;
        let sphere, currentTexture;
        let hotspots = [];
        let isFullscreen = false;
        let geometry = null;
        
        // 全景图配置
        const scenes = {
            pano1: {
                url: 'file/image/20250917/pano.jpg',
                hotspots: [
                    { position: { x: 0, y: 0, z: -400 }, text: "主要景点" },
                    { position: { x: -300, y: 100, z: 200 }, text: "观景台" }
                ]
            },
            pano2: {
                url: 'file/image/20250917/pano1.jpg',
                hotspots: [
                    { position: { x: 200, y: 50, z: 300 }, text: "花园区域" },
                    { position: { x: -200, y: -50, z: 300 }, text: "休息区" }
                ]
            },
            pano3: {
                url: 'file/image/20250917/pano.jpg',
                hotspots: [
                    { position: { x: 0, y: 150, z: -350 }, text: "天空视角" },
                    { position: { x: 400, y: 0, z: 0 }, text: "东侧入口" }
                ]
            }
        };
        
        // 初始化场景
        function init() {
            // 创建场景
            scene = new THREE.Scene();
            
            // 创建相机
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.set(0, 0, 0.1);
            
            // 创建渲染器
            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.setPixelRatio(window.devicePixelRatio);
            document.getElementById('canvas-container').appendChild(renderer.domElement);
            
            // 创建球体几何体
            geometry = new THREE.SphereGeometry(500, 60, 40);
            geometry.scale(-1, 1, 1); // 反转几何体使纹理在内部可见
            
            // 加载默认全景图
            loadPanorama(scenes.pano1.url, scenes.pano1.hotspots);
            
            // 添加轨道控制器
            controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.enableZoom = true;
            controls.zoomSpeed = 0.5;
            controls.rotateSpeed = 0.3;
            controls.minDistance = 0.1;
            controls.maxDistance = 1000;
            
            // 添加窗口调整事件监听
            window.addEventListener('resize', onWindowResize);
            
            // 添加UI事件监听
            setupEventListeners();
            
            // 开始动画循环
            animate();
        }
        
        // 加载全景图
        function loadPanorama(url, hotspotData) {
            const textureLoader = new THREE.TextureLoader();
            
            // 显示加载界面
            document.querySelector('.loading-overlay').style.display = 'flex';
            
            // 添加错误处理，如果图片加载失败使用占位图
            textureLoader.load(url, 
                (texture) => {
                    // 移除旧的球体（如果存在）
                    if (sphere) {
                        scene.remove(sphere);
                        sphere.geometry.dispose();
                        sphere.material.dispose();
                    }
                    
                    // 清除旧的热点
                    clearHotspots();
                    
                    // 创建新材质和球体
                    const material = new THREE.MeshBasicMaterial({ map: texture });
                    sphere = new THREE.Mesh(geometry, material);
                    scene.add(sphere);
                    
                    // 存储当前纹理
                    currentTexture = texture;
                    
                    // 添加热点
                    if (hotspotData && hotspotData.length > 0) {
                        addHotspots(hotspotData);
                    }
                    
                    // 隐藏加载界面
                    setTimeout(() => {
                        document.querySelector('.loading-overlay').style.display = 'none';
                    }, 500);
                }, 
                undefined, 
                (error) => {
                    console.error('Error loading panorama:', error);
                    document.querySelector('.loading-text').textContent = '加载失败，使用默认场景';
                    
                    // 使用默认颜色场景
                    const material = new THREE.MeshBasicMaterial({ color: 0x3366cc });
                    sphere = new THREE.Mesh(geometry, material);
                    scene.add(sphere);
                    
                    setTimeout(() => {
                        document.querySelector('.loading-overlay').style.display = 'none';
                    }, 1000);
                }
            );
        }
        
        // 添加热点
        function addHotspots(hotspotData) {
            hotspotData.forEach((hotspotInfo) => {
                // 创建热点div元素
                const hotspot = document.createElement('div');
                hotspot.className = 'hotspot';
                
                // 创建工具提示
                const tooltip = document.createElement('div');
                tooltip.className = 'hotspot-tooltip';
                tooltip.textContent = hotspotInfo.text;
                hotspot.appendChild(tooltip);
                
                // 添加到容器
                document.getElementById('canvas-container').appendChild(hotspot);
                
                // 存储热点引用
                hotspots.push({
                    element: hotspot,
                    position: hotspotInfo.position
                });
                
                // 添加点击事件
                hotspot.addEventListener('click', () => {
                    alert(`您点击了: ${hotspotInfo.text}`);
                });
            });
            
            // 更新热点位置
            updateHotspotPositions();
        }
        
        // 清除所有热点
        function clearHotspots() {
            hotspots.forEach(hotspot => {
                if (hotspot.element && hotspot.element.parentNode) {
                    hotspot.element.parentNode.removeChild(hotspot.element);
                }
            });
            hotspots = [];
        }
        
        // 更新热点位置（基于相机方向）
        function updateHotspotPositions() {
            if (hotspots.length === 0) return;
            
            hotspots.forEach(hotspot => {
                // 将3D位置转换为屏幕坐标
                const vector = new THREE.Vector3(
                    hotspot.position.x,
                    hotspot.position.y,
                    hotspot.position.z
                );
                
                vector.project(camera);
                
                const x = (vector.x * 0.5 + 0.5) * window.innerWidth;
                const y = -(vector.y * 0.5 - 0.5) * window.innerHeight;
                
                // 更新热点位置
                hotspot.element.style.left = `${x}px`;
                hotspot.element.style.top = `${y}px`;
                
                // 如果热点在相机后面，隐藏它
                if (vector.z > 1) {
                    hotspot.element.style.display = 'none';
                } else {
                    hotspot.element.style.display = 'block';
                }
            });
        }
        
        // 窗口调整大小处理
        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
            updateHotspotPositions();
        }
        
        // 缩放控制函数
        function zoomIn() {
            // 通过调整相机位置来模拟缩放
            camera.fov -= 5;
            if (camera.fov < 10) camera.fov = 10;
            camera.updateProjectionMatrix();
        }
        
        function zoomOut() {
            // 通过调整相机位置来模拟缩放
            camera.fov += 5;
            if (camera.fov > 100) camera.fov = 100;
            camera.updateProjectionMatrix();
        }
        
        // 设置事件监听器
        function setupEventListeners() {
            // 缩放按钮
            document.getElementById('zoom-in').addEventListener('click', zoomIn);
            document.getElementById('zoom-out').addEventListener('click', zoomOut);
            
            // 重置视图
            document.getElementById('reset-view').addEventListener('click', () => {
                controls.reset();
                camera.fov = 75;
                camera.updateProjectionMatrix();
            });
            
            // VR模式
            document.getElementById('vr-mode').addEventListener('click', () => {
                alert('VR模式需要VR设备支持，此功能为演示版本');
            });
            
            // 切换信息面板
            document.querySelector('.toggle-info').addEventListener('click', () => {
                document.querySelector('.info-panel').classList.toggle('hidden');
            });
            
            // 全屏模式
            document.querySelector('.fullscreen-btn').addEventListener('click', toggleFullscreen);
            
            // 场景选择
            document.querySelectorAll('.scene-thumb').forEach(thumb => {
                thumb.addEventListener('click', () => {
                    // 更新激活状态
                    document.querySelectorAll('.scene-thumb').forEach(t => {
                        t.classList.remove('active');
                    });
                    thumb.classList.add('active');
                    
                    // 加载新场景
                    const sceneName = thumb.getAttribute('data-scene');
                    loadPanorama(scenes[sceneName].url, scenes[sceneName].hotspots);
                });
            });
            
            // 双击全屏
            renderer.domElement.addEventListener('dblclick', toggleFullscreen);
        }
        
        // 切换全屏
        function toggleFullscreen() {
            if (!document.fullscreenElement) {
                document.documentElement.requestFullscreen().catch(err => {
                    console.error(`全屏错误: ${err.message}`);
                });
                isFullscreen = true;
            } else {
                if (document.exitFullscreen) {
                    document.exitFullscreen();
                    isFullscreen = false;
                }
            }
        }
        
        // 动画循环
        function animate() {
            requestAnimationFrame(animate);
            controls.update();
            updateHotspotPositions();
            renderer.render(scene, camera);
        }
        
        // 页面加载完成后初始化
        window.addEventListener('load', init);
    </script>
</body>
</html>